package com.example.spring_mysql

import cn.dev33.satoken.stp.StpUtil
import com.example.spring_mysql.controller.AsyncService
import com.example.spring_mysql.entity.User
import com.example.spring_mysql.redis.RedisMessageConfiguration
import com.example.spring_mysql.service.IUserService
import jakarta.servlet.FilterRegistration
import jakarta.servlet.ServletContext
import jakarta.servlet.http.HttpServletRequest
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory
import org.springframework.data.redis.core.StringRedisTemplate
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.messaging.MessageChannel
import org.springframework.messaging.support.MessageBuilder
import org.springframework.security.access.prepost.PreAuthorize
import org.springframework.validation.annotation.Validated
import org.springframework.web.bind.annotation.*
import java.time.LocalDate
import java.time.LocalDateTime


@RestController
@RequestMapping("/")
@Validated
class MyControl {
    @Autowired
    lateinit var userRepository: IUserService

    @GetMapping("hello")
    fun hello(): String {
        return "hello"
    }

    @GetMapping("/public/hello")
    fun publicHello(): String {
        return "Hello Public!"
    }

    @GetMapping("/admin/hello")
    fun adminHello(): String {
        return "Hello Admin!"
    }

    @PreAuthorize("hasRole('ROLE_ADMIN')")
    @GetMapping("/user/hello")
    fun userHello(): String {
        return "Hello Authenticated User!"
    }

    @GetMapping("insert")
    fun insert(
        @RequestParam username: String, @RequestParam password: String
    ): String {
        userRepository.save(
            User().apply { this.username = username; this.password = password })
        return "Inserted user: $username"
    }

    @GetMapping("getUsers")
    fun getUsers(
    ): String {
        return userRepository.getUsersBySelf().toString()
    }

    @GetMapping("find")
    fun find(
        @RequestParam username: String, @RequestParam password: String
    ): String {
        return userRepository.selectByUsernameAndPsw(username, password).toString()
    }

    @GetMapping("delete/{id}")
    fun deleteUser(
        @PathVariable id: String
    ): String {
        return "删除结果：" + userRepository.removeById(id).toString()
    }

    // 1. 直接接收时间参数（自动转换）
    @GetMapping("/test1")
    fun test1(
        @RequestParam date: LocalDate, @RequestParam dateTime: LocalDateTime
    ): String {
        return "Received date: $date, dateTime: $dateTime"
    }


    @Autowired
    lateinit var asyncService: AsyncService

    @GetMapping("/async/test")
    fun asyncTest(
    ): String {
        println("" + Thread.currentThread().name + "  " + System.currentTimeMillis() + "  " + "asyncTest")
        val completableFuture = asyncService.doAsyncTask("name");
        completableFuture.exceptionally { ex ->
            println("捕获到异步异常: ${ex.message}")
            null
        }
        return "异步任务已触发"
    }

    // 测试登录，浏览器访问： http://localhost:8081/user/doLogin?username=zhang&password=123456
    @RequestMapping("doLogin")
    fun doLogin(username: String, password: String): String {
        println("token:" + StpUtil.getTokenValue())
        // 此处仅作模拟示例，真实项目需要从数据库中查询数据进行比对
        if ("zhang" == username && "123456" == password) {
            StpUtil.login(10001)
            return "登录成功"
        }
        return "登录失败"
    }

//    @Autowired
//    lateinit var handlerMapping: RequestMappingHandlerMapping
    // 查询登录状态，浏览器访问： http://localhost:8081/user/isLogin

    @Autowired
    lateinit var servletContext: ServletContext

    @RequestMapping("isLogin")
    fun isLogin(request: HttpServletRequest): String {
//        println("token:" + StpUtil.getTokenValue())
//        val chain = handlerMapping.getHandler(request)
//        for (interceptor in chain!!.interceptors!!) {
//            println("执行链中的拦截器: " + interceptor.javaClass.name)
//        }
        printAllFilters()

        return "当前会话是否登录：" + StpUtil.isLogin()
    }


    fun printAllFilters() {
        val filterRegistrations: Map<String, FilterRegistration?> = servletContext.filterRegistrations
        filterRegistrations.forEach { (name: String?, registration: FilterRegistration?) ->
            println("Filter name: " + name + ", class: " + registration?.className)
        }
    }

    @RequestMapping("permission")
    fun permission(): String {
        // 获取：当前账号所拥有的权限集合
        if (!StpUtil.isLogin()) {
            StpUtil.login(101)
        }
        println(StpUtil.getPermissionList())

        StpUtil.checkPermission("user.add.admin");
        return "permission"
    }

    @Autowired
    lateinit var redisTemplate: StringRedisTemplate

    @GetMapping("redis/put/{key}")
    fun redisPut(@PathVariable key: String, @RequestParam value: String): String {
        redisTemplate.opsForValue()[key] = "张三"
        return "redis put: $value success"
    }

    @GetMapping("redis/check/{key}")
    fun redisPut(@PathVariable key: String): String {
        try {
            val str = redisTemplate.opsForValue().get(key) as String
            return ResponseEntity.ok().body(str).toString()
        } catch (e: Exception) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.message).toString();
        }
    }

    @GetMapping("redis/convertAndSend")
    fun convertAndSend(@RequestParam msg: String): String {
        redisTemplate.convertAndSend(RedisMessageConfiguration.WS_TO_SERVICE, msg)
        return "send success"
    }

    @Autowired
    lateinit var configurableListableBeanFactory: ConfigurableListableBeanFactory

    @GetMapping("validation/test")
    fun validation(@RequestParam @NotZero(message = "用户ID不能为0") number: Int): String {
        return "validation test"
    }

    @Autowired
    @Qualifier("myInputChannel")
    lateinit var inputChannel: MessageChannel

    @GetMapping("messageChannel/test")
    fun messageChannel(): String {
        val message = MessageBuilder.withPayload("Hello Integration!").build()
        return inputChannel.send(message).toString()
    }

}